﻿using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using DarkUI.Forms;
using MySql.Data.MySqlClient;
using ShkSimulation.core.dao.input.resource;
using ShkSimulation.carsharing;
using ShkSimulation.desktop.setting;
using ShkSimulation.desktop.setting.tools;
using ShkSimulation.desktop.util;

namespace ShkSimulation.desktop {
    public partial class ConfigForm : DarkForm {

        public readonly static string FormatPattern = "yyyy/MM/dd HH:mm:ss";
        
        public ConfigForm() {
            InitializeComponent();
            Init();
        }

        private void Init() {
            ConnectionStatusLabel.Text = "";
            BindResourceType();
            BindNavigateType();
            BindSimulationConfig();
            BindRunConfig();
            BindStartTime();
            BindDataSource();
            void BindSimulationConfig() {
                StationDataTextBox.DataBindings.Clear();
                RoadDataTextBox.DataBindings.Clear();
                DemandDataTextBox.DataBindings.Clear();
                NavigateDataTextBox.DataBindings.Clear();
                EnableDispatchCheckBox.DataBindings.Clear();
                UpDispatchNumeric.DataBindings.Clear();
                DownDispatchNumeric.DataBindings.Clear();
                
                StationDataTextBox.DataBindings.Add("Text", ConfigManager.UserSimulationConfig, "站台文件", false, DataSourceUpdateMode.OnPropertyChanged);
                RoadDataTextBox.DataBindings.Add("Text", ConfigManager.UserSimulationConfig, "道路文件", false, DataSourceUpdateMode.OnPropertyChanged);
                DemandDataTextBox.DataBindings.Add("Text", ConfigManager.UserSimulationConfig, "需求文件", false, DataSourceUpdateMode.OnPropertyChanged);
                NavigateDataTextBox.DataBindings.Add("Text", ConfigManager.UserSimulationConfig, "导航文件", false, DataSourceUpdateMode.OnPropertyChanged);
                EnableNavigateCheckBox.DataBindings.Add("Checked", ConfigManager.UserSimulationConfig, "启用导航", false, DataSourceUpdateMode.OnPropertyChanged);
                EnableDispatchCheckBox.DataBindings.Add("Checked", ConfigManager.UserSimulationConfig, "启用调度", false, DataSourceUpdateMode.OnPropertyChanged);
                UpDispatchNumeric.DataBindings.Add("Value", ConfigManager.UserSimulationConfig, "调度触发上阈值", false, DataSourceUpdateMode.OnPropertyChanged);
                DownDispatchNumeric.DataBindings.Add("Value", ConfigManager.UserSimulationConfig, "调度触发下阈值", false, DataSourceUpdateMode.OnPropertyChanged);
            }
            void BindNavigateType() {
                // NavigateType
                NavigateTypeComboBox.BindToEnumName(typeof(NavigateType));
                Binding binding = new Binding("SelectedIndex", ConfigManager.UserSimulationConfig, "导航类型");
                binding.Parse += BindingOnParse;
                binding.Format += BindingOnFormat;
                binding.ControlUpdateMode = ControlUpdateMode.OnPropertyChanged;
                binding.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
                NavigateTypeComboBox.DataBindings.Add(binding);
                void BindingOnFormat(object sender, ConvertEventArgs e) {
                    e.Value = NavigateTypeComboBox.Items.IndexOf(((NavigateType) e.Value).ToString());
                }
                void BindingOnParse(object sender, ConvertEventArgs e) {
                    e.Value = Enum.Parse(typeof(NavigateType), (string)NavigateTypeComboBox.SelectedItem, true);
                }
            }        
            void BindResourceType() {
                // ResourceType
                ResourceTypeComboBox.BindToEnumName(typeof(ResourceType));
                Binding binding = new Binding("SelectedIndex", ConfigManager.UserSimulationConfig, "输入类型");
                binding.Parse += BindingOnParse;
                binding.Format += BindingOnFormat;
                binding.ControlUpdateMode = ControlUpdateMode.OnPropertyChanged;
                binding.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
                ResourceTypeComboBox.DataBindings.Add(binding);
                void BindingOnFormat(object sender, ConvertEventArgs e) {
                    e.Value = ResourceTypeComboBox.Items.IndexOf(((ResourceType) e.Value).ToString());
                }
                void BindingOnParse(object sender, ConvertEventArgs e) {
                    e.Value = Enum.Parse(typeof(ResourceType), (string)ResourceTypeComboBox.SelectedItem, true);
                }
            }        
            void BindRunConfig() {
                SimulationSpanNumeric.DataBindings.Clear();
                ObserveSpanNumeric.DataBindings.Clear();
                
                RealTimeCheckBox.DataBindings.Add("Checked", ConfigManager.UserRunConfig, "真实时间", false, DataSourceUpdateMode.OnPropertyChanged);
                
                Binding binding = new Binding("Value", ConfigManager.UserRunConfig, "仿真时长");
                binding.Parse += FormExtensions.ParseDecimalToTimeSpan;
                binding.Format += FormExtensions.ParseTimeSpanToDecimal;
                binding.ControlUpdateMode = ControlUpdateMode.OnPropertyChanged;
                binding.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
                SimulationSpanNumeric.DataBindings.Add(binding);
                
                Binding ovserveSpanNumericBinding = new Binding("Value", ConfigManager.UserRunConfig, "观察间隔");
                ovserveSpanNumericBinding.Parse += FormExtensions.ParseDecimalToTimeSpan;
                ovserveSpanNumericBinding.Format += FormExtensions.ParseTimeSpanToDecimal;
                ovserveSpanNumericBinding.ControlUpdateMode = ControlUpdateMode.OnPropertyChanged;
                ovserveSpanNumericBinding.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
                ObserveSpanNumeric.DataBindings.Add(ovserveSpanNumericBinding);
            }
            void BindStartTime() {
                StartTimeTextBox.Text = ConfigManager.UserRunConfig.仿真开始时刻.ToString(FormatPattern);
                StartTimeFormatLabel.ResetBindings();
                Binding binding = new Binding("Text", ConfigManager.UserRunConfig, "仿真开始时刻");
                binding.Parse += (sender, args) => {
                    DateTime startTime;
                    DateTime.TryParse(((string) args.Value), out startTime);
                    args.Value = startTime;
                };
                binding.Format += (sender, args) => {
                    args.Value = ((DateTime) args.Value).ToString(FormatPattern);
                };
                binding.ControlUpdateMode = ControlUpdateMode.OnPropertyChanged;
                binding.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
                StartTimeFormatLabel.DataBindings.Add(binding);     
            }
            void BindDataSource() {
                IPUrlTextBox.DataBindings.Add("Text", ConfigManager.UserSystemConfig, "IP地址", false, DataSourceUpdateMode.OnPropertyChanged);
                DatabaseTextBox.DataBindings.Add("Text", ConfigManager.UserSystemConfig, "数据库名", false, DataSourceUpdateMode.OnPropertyChanged);
                UsernameTextBox.DataBindings.Add("Text", ConfigManager.UserSystemConfig, "用户名", false, DataSourceUpdateMode.OnPropertyChanged);
                PasswordTextBox.DataBindings.Add("Text", ConfigManager.UserSystemConfig, "密码", false, DataSourceUpdateMode.OnPropertyChanged);
                PortTextBox.DataBindings.Add("Text", ConfigManager.UserSystemConfig, "端口", false, DataSourceUpdateMode.OnPropertyChanged);
            }

        }

        private void StartTimeApplyButton_Click(object sender, EventArgs e) {
            DateTime startTime;
            if (DateTime.TryParse(StartTimeTextBox.Text, out startTime)) {
                StartTimeFormatLabel.Text = startTime.ToString(FormatPattern);
            } else {
                MessageBox.Show(@"时间字符串格式错误", @"提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void SetStartTodayButton_Click(object sender, EventArgs e) {
            StartTimeTextBox.Text = DateTime.Now.ToString(FormatPattern);
            StartTimeFormatLabel.Text = StartTimeTextBox.Text;
        }

        private void ResetStartTimeButton_Click(object sender, EventArgs e) {
            StartTimeTextBox.Text = DateTime.MinValue.ToString(FormatPattern);
            StartTimeFormatLabel.Text = StartTimeTextBox.Text;
        }

        private void OpenStationDataButton_Click(object sender, EventArgs e) {
            string filePath = FileUtil.OpenFile(OpenFileDialog);
            if (filePath == null) {
                return;
            }
            StationDataTextBox.Text = filePath;
        }

        private void OpenRoadDataButton_Click(object sender, EventArgs e) {
            string filePath = FileUtil.OpenFile(OpenFileDialog);
            if (filePath == null) {
                return;
            }
            RoadDataTextBox.Text = filePath;
        }

        private void OpenDemandDataButton_Click(object sender, EventArgs e) {
            string filePath = FileUtil.OpenFile(OpenFileDialog);
            if (filePath == null) {
                return;
            }
            DemandDataTextBox.Text = filePath;
        }

        private void OpenNavigateDataButton_Click(object sender, EventArgs e) {
            string filePath = FileUtil.OpenFile(OpenFileDialog);
            if (filePath == null) {
                return;
            }
            NavigateDataTextBox.Text = filePath;
        }

        private void TestConnectionButton_Click(object sender, EventArgs e) {
            String connectionUrl = $"server={ConfigManager.UserSystemConfig.IP地址};" +
                               $"port={ConfigManager.UserSystemConfig.端口};" +
                               $"user={ConfigManager.UserSystemConfig.用户名};" +
                               $"password={ConfigManager.UserSystemConfig.密码};" +
                               $"database={ConfigManager.UserSystemConfig.数据库名};";
            try {
                MySqlConnection con = new MySqlConnection(connectionUrl);
                Task task = con.OpenAsync();
                task.Wait(TimeSpan.FromSeconds(2));
                if (task.IsCompletedSuccessfully) {
                    ConnectionStatusLabel.Text = @"连接成功";
                    con.Close();
                } else {
                    ConnectionStatusLabel.Text = @"连接失败";
                }
            } catch (Exception exception) {
                Console.WriteLine(exception);
                ConnectionStatusLabel.Text = @"连接失败";
            }
        }

        private void NavigateTypeComboBox_SelectedIndexChanged(object sender, EventArgs e) {
            
        }

        private void CertainButton_Click(object sender, EventArgs e) {
            this.Close();
        }

        private void RealTimeCheckBox_CheckedChanged(object sender, EventArgs e) {
            double runTime = (int)SimulationSpanNumeric.Value;
            double observe = (int)ObserveSpanNumeric.Value;
            if (RealTimeCheckBox.Checked) {
                ConfigManager.UserRunConfig.仿真时长 = TimeSpan.FromSeconds(runTime);
                ConfigManager.UserRunConfig.观察间隔 = TimeSpan.FromSeconds(observe);
                RunTimeUnitLabel.Text = @"秒";
                ObserveSpanUnitLabel.Text = @"秒";
            } else {
                ConfigManager.UserRunConfig.仿真时长 = TimeSpan.FromDays(runTime);
                ConfigManager.UserRunConfig.观察间隔 = TimeSpan.FromDays(observe);
                RunTimeUnitLabel.Text = @"天";
                ObserveSpanUnitLabel.Text = @"天";
            }
        }
    }
}
